/**
  * File  : Thread.cc
  * Time  : 2014-12-12 21:23
  * Author: KashingLee 
  * Ref   :  mooon
  */
#include "Thread.h"

void *ThreadFunc (void *arg_this) {
  Thread *p = static_cast<Thread *>(arg_this);
  p->Run();
  return NULL;
}

Thread::Thread () {
  int ret = pthread_attr_init(&attr_);  
  if (ret) {
    throw ThreadException(THREAD_ATTR_INIT);
  }
}

Thread::~Thread () {
  pthread_attr_destroy(&attr_);
}

uint32_t Thread::CurrentThreadId () {
  return static_cast<uint32_t>(pthread_self());
}

void Thread::Join () {
  if ( Thread::CurrentThreadId() != this->thread_id() ) {
    int ret = pthread_join(id_, NULL);
    if (ret) {
      throw ThreadException(THREAD_JOIN);
    }
  }
}

void Thread::Detach () {
  int ret = pthread_detach(id_);
  if (ret) {
    throw ThreadException(THREAD_DETACH);
  }
}

bool Thread::IsJoinable () {
  int detach_state;
  int ret = pthread_attr_getdetachstate(&attr_, &detach_state);
  if (ret) {
    throw ThreadException(THREAD_GET_ATTR);
  }
  return ret == PTHREAD_CREATE_JOINABLE;
}

void Thread::Start (bool be_detached) {
  if (!BeforeRun()) {
   throw ThreadException(THREAD_BEFORE_RUN); 
  }
  int ret = 0;
  ret = pthread_attr_setdetachstate(&attr_,\
      be_detached ? PTHREAD_CREATE_DETACHED: PTHREAD_CREATE_JOINABLE);

  ret = pthread_create(&id_, &attr_, ThreadFunc, this);
  if (ret) {
    throw ThreadException(THREAD_CREATE);
  }
}
